#ifndef __GAME_NET_H__
#define __GAME_NET_H__

#include "game_def.h"
#include "game_tl.h"

// 网络包最大尺寸
#define CNET_PACKAGE_MAXLEN CGameNetMsg_T::BUFF_BODY_MAX_LEN
// 网络饱和定义百分比
#define CNET_BUSY_PERCENT 80
// 网络连接数上限(一个服务器最多可接受的连接数)
#define CNET_NETLINK_MAXNUM 8000
// 注册网络消息
#define NETMSG_REG(p, x, f) (p)->RegCmd((x)&CNETLINK_CMD_MASK, CNetMsgListener(this, f))

enum
{
  CNETLINK_TCP_SERVER = 0, //!< 服务器端
  CNETLINK_TCP_CLIENT,     //!< 客户端
  CNETLINK_UDP,

  CNETLINK_FLAG_NONE = 0x0000,       //!< 网络标志：无
  CNETLINK_FLAG_CODE = 0x0001,       //!< 网络标志：加密
  CNETLINK_FLAG_COMPRESS = 0x0002,   //!< 网络标志：压缩
  CNETLINK_FLAG_WPE_FILTER = 0x0004, //!< 网络标记：wpe过滤器
  CNETLINK_FLAG_DIRECT = 0x0080,     //!< 网络标志：是否直接发送消息
  CNETLINK_FLAG_FLASH = 0x0100,      //!< 网络标志：支持flash
  CNETLINK_FLAG_SERVERMODE = 0x0200, //!< 网络标志：服务器对服务器模式
  CNETLINK_FLAG_TGW = 0x0400,        //!< 网络标志：支持TGW
  CNETLINK_FLAG_TGW_STRICT = 0x0800, //!< 网络标志：支持TGW严格模式
  CNETLINK_FLAG_SIGN = 0x0060,       //!< 网络数据校验标志(系统保留)
  CNETLINK_FLAG_SIGN_MASK = 0x00f0,  //!< 网络数据校验标志掩码(系统保留)
  CNETLINK_FLAG_NONE_DEBUG = 0x1000, //!< 是否无调试信息

  CNETLINK_CMD_MASK = 0x7fff,      //!< 网络消息掩码
  CNETLINK_CMD_BUSY_MASK = 0x8000, //!< 网络消息忽略掩码(在消息缓冲区大于80%的时候开始丢包)

  PXNET_MSGPOOL_SIZE_TINY = 1024 * 1024,        //!< 缓冲区大小：小型
  PXNET_MSGPOOL_SIZE_NORMAL = 10 * 1024 * 1024, //!< 缓冲区大小：默认普通大小
  PXNET_MSGPOOL_SIZE_HUGE = 100 * 1024 * 1024,  //!< 缓冲区大小：大型

  PXNET_STREAM_SIZE_NORMAL = 32 * 1024, //!< 网络流大小：默认普通大小
  PXNET_STREAM_SIZE_HUGE = 1024 * 1024, //!< 网络流大小：大型

  // 网络消息定义
  NMSG_NULL = 0,       //!< 网络消息：空消息
  NMSG_NET_CONNECT,    //!< 网络消息：连接上
  NMSG_NET_DISCONNECT, //!< 网络消息：断开连接
  NMSG_MSGCODEMODE,    //!< 网络消息：网络消息加密模式同步
  NMSG_HEART_PING,     //!< 网络消息：ping
  NMSG_HEART_PING_RET, //!< 网络消息：ping返回
  NMSG_USERDEF = 0x10, //!< 用户自定义消息开始(网络消息系统保留部分，不允许用户进行发送)
};

typedef UINT8 c_net_sign_t;         //!< 网络标记类型
typedef UINT16 c_net_index_t;       //!< 网络索引id类型
typedef UINT16 c_net_cmd_t;         //!< 网络命令类型
typedef UINT16 c_net_len_t;         //!< 网络消息长度类型
typedef UINT32 c_net_key_t;         //!< 网络加密密匙
typedef const char *c_net_cmdstr_t; //!< 网络命令字符串类型

/**
 *@brief 网络消息(命令标记,命令码,命令数据长度,命令数据)
 */
struct CGameNetMsg_T
{
  enum
  {
    BUFF_MAX_LEN = 8 * 1024,                                     //!< 缓冲区大小
    BUFF_OFFSET_SIGN = 0,                                        //!< 标记偏移
    BUFF_OFFSET_CMD = BUFF_OFFSET_SIGN + sizeof(c_net_sign_t),   //!< 命令偏移
    BUFF_OFFSET_CMDLEN = BUFF_OFFSET_CMD + sizeof(c_net_cmd_t),  //!< 命令长度偏移
    BUFF_OFFSET_BODY = BUFF_OFFSET_CMDLEN + sizeof(c_net_len_t), //!< 命令数据偏移

    BUFF_HEAD_LEN = BUFF_OFFSET_BODY,                    //!< 消息头长度
    BUFF_BODY_MAX_LEN = BUFF_MAX_LEN - BUFF_OFFSET_BODY, //!< 消息内容最大长度
  };
  UINT8 buff[BUFF_MAX_LEN]; // px_net_index_t,px_net_sign_t,px_net_cmd_t,px_net_len_t
  CGameNetMsg_T();
  CGameNetMsg_T(c_net_index_t index, c_net_cmd_t cmd, const void *body, c_net_len_t len_body);
  CGameNetMsg_T(c_net_cmd_t cmd, const void *body, c_net_len_t len_body);
  ~CGameNetMsg_T();
  /**
   *@brief 获取网络消息数据
   */
  const void *net_data(void) const;
  /**
   *@brief 网络消息大小
   */
  c_net_len_t net_size(void) const;
  /**
   *@brief sign
   */
  inline c_net_sign_t &net_sign(void);
  /**
   *@brief 命令
   */
  inline c_net_cmd_t &net_cmd(void);
  /**
   *@brief 命令
   */
  inline c_net_cmd_t net_cmd(void) const;
  /**
   *@brief 命令值长度
   */
  inline c_net_len_t &net_bodylen(void);
  /**
   *@brief 命令值长度
   */
  inline c_net_len_t net_bodylen(void) const;
  /**
   *@brief 命令值
   */
  inline void *net_body(void);
};

/**
 *@brief 网络消息监听
 *@param[in] 网络连接
 *@param[in] 命令
 *@param[in] 命令数据
 *@param[in] 命令数据长度
 *@return 是否成功处理消息
 */
typedef CMemFun_t<CGameObject, BOOL, c_net_index_t, c_net_cmd_t, void *, c_net_len_t> CNetMsgListener;

/**
 *@brief 网络消息监听
 *@param[in] 网络连接
 *@param[in] 命令数据
 *@param[in] 命令数据长度
 *@return 返回处理的字节数
 */
typedef CMemFun_t<CGameObject, c_net_len_t, c_net_index_t, void *, c_net_len_t> CDirectRecvNetMsgFunc_T;




#endif
